package com.basic.business.wholeIndicators.service.impl;

import cn.idev.excel.EasyExcel;
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.read.listener.ReadListener;
import cn.idev.excel.util.ListUtils;
import com.basic.business.goodsIndicators.domain.TGoodsIndicators;
import com.basic.business.indicatorsFile.service.ITIndicatorsFileService;
import com.basic.business.wholeIndicators.domain.TWholeStationIndicators;
import com.basic.business.wholeIndicators.dto.TWholeStationIndicatorsDto;
import com.basic.business.wholeIndicators.mapper.TWholeStationIndicatorsMapper;
import com.basic.business.wholeIndicators.service.ITWholeStationIndicatorsService;
import com.basic.common.core.service.impl.BaseServiceImpl;
import com.basic.common.utils.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static cn.idev.excel.support.ExcelTypeEnum.CSV;

/**
 * 全站推指标数据Service业务层处理
 *
 * @author zhaoxy_jn@163.com
 */
@Service
public class TWholeStationIndicatorsServiceImpl extends BaseServiceImpl<TWholeStationIndicatorsMapper,TWholeStationIndicators> implements ITWholeStationIndicatorsService {

    @Resource
    private TWholeStationIndicatorsMapper tWholeStationIndicatorsMapper;

    @Resource
    private ITIndicatorsFileService itIndicatorsFileService;

    @Override
    public int deleteByFileId(String fileId) {
        return tWholeStationIndicatorsMapper.deleteByFileId(fileId);
    }

    @Override
    public int saveBatch(List<TWholeStationIndicators> list) {
        return tWholeStationIndicatorsMapper.saveBatch(list);
    }

    @Override
    public int deleteOldData(String fileId, String storeId, Date statDate, List<String> mainBodyIdList) {
        return tWholeStationIndicatorsMapper.deleteOldData(fileId, storeId, statDate, mainBodyIdList);
    }

    @Override
    public int deleteByGoodsId(List<TGoodsIndicators> goodsList) {
        return tWholeStationIndicatorsMapper.deleteByGoodsId(goodsList);
    }

    @Transactional
    @Override
    public void uploadIndicatorsData(MultipartFile file, Date selectDate, String wholeStoreId, String fileHash) {
        //文件上传
        String fileId = itIndicatorsFileService.uploadIndicatorsFile(file, selectDate, wholeStoreId, fileHash, 3);

        try {
            EasyExcel.read(file.getInputStream(), TWholeStationIndicatorsDto.class, new ReadListener<TWholeStationIndicatorsDto>(){

                /**
                 * 单次缓存的数据量
                 */
                public static final int BATCH_COUNT = 500;

                /**
                 *临时存储
                 */
                private List<TWholeStationIndicators> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);


                /**
                 * 解析调用
                 * @param data
                 * @param analysisContext
                 */
                @Override
                public void invoke(TWholeStationIndicatorsDto data, AnalysisContext analysisContext) {
                    TWholeStationIndicators tWholeStationIndicators = new TWholeStationIndicators();

                    tWholeStationIndicators.setId(null);
                    tWholeStationIndicators.setStoreId(wholeStoreId);
                    tWholeStationIndicators.setFileId(fileId);
                    try {
                        tWholeStationIndicators.setStatDate(parseDate(data.getStatDate()));
                    } catch (ParseException e) {
                        throw new RuntimeException(e);
                    }
                    tWholeStationIndicators.setMainBodyId(data.getMainBodyId());
                    tWholeStationIndicators.setMainBodyType(data.getMainBodyType());
                    tWholeStationIndicators.setMainBodyName(data.getMainBodyName());
                    tWholeStationIndicators.setCostAmount(convertField(data.getCostAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getCostAmount().replace(",","")));
                    tWholeStationIndicators.setTotalTransactionAmount(convertField(data.getTotalTransactionAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getTotalTransactionAmount().replace(",","")));
                    tWholeStationIndicators.setActualProductionRatio(convertField(data.getActualProductionRatio())?0:Double.parseDouble(data.getActualProductionRatio().replace(",","")));
                    tWholeStationIndicators.setImpressions(convertField(data.getImpressions())?0:Integer.parseInt(data.getImpressions().replace(",","")));
                    tWholeStationIndicators.setHits(convertField(data.getHits())?0:Integer.parseInt(data.getHits().replace(",","")));
                    tWholeStationIndicators.setClickRate(convertField(data.getClickRate())? String.valueOf(0) :data.getClickRate());
                    tWholeStationIndicators.setAverageClickCost(convertField(data.getAverageClickCost())? BigDecimal.valueOf(0) :new BigDecimal(data.getAverageClickCost().replace(",","")));
                    tWholeStationIndicators.setThousandShowCost(convertField(data.getThousandShowCost())? BigDecimal.valueOf(0) :new BigDecimal(data.getThousandShowCost().replace(",","")));
                    tWholeStationIndicators.setTotalTransactionsNumber(convertField(data.getTotalTransactionsNumber())?0:Integer.parseInt(data.getTotalTransactionsNumber().replace(",","")));
                    tWholeStationIndicators.setClickConversionRate(convertField(data.getClickConversionRate())? String.valueOf(0) :data.getClickConversionRate());
                    tWholeStationIndicators.setTotalShopCartNumber(convertField(data.getTotalShopCartNumber())?0:Integer.parseInt(data.getTotalShopCartNumber().replace(",","")));
                    tWholeStationIndicators.setCollectTreasureNumber(convertField(data.getCollectTreasureNumber())?0:Integer.parseInt(data.getCollectTreasureNumber().replace(",","")));
                    tWholeStationIndicators.setCollectTreasureBuyNumber(convertField(data.getCollectTreasureBuyNumber())?0:Integer.parseInt(data.getCollectTreasureBuyNumber().replace(",","")));
                    tWholeStationIndicators.setBoostShowNumber(convertField(data.getBoostShowNumber())? 0 :Integer.parseInt(data.getBoostShowNumber().replace(",","")));
                    tWholeStationIndicators.setBoostClickNumber(convertField(data.getBoostClickNumber())? 0 :Integer.parseInt(data.getBoostClickNumber().replace(",","")));
                    tWholeStationIndicators.setDirectBusinessAmount(convertField(data.getDirectBusinessAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getDirectBusinessAmount().replace(",","")));
                    tWholeStationIndicators.setDirectBusinessNumber(convertField(data.getDirectBusinessNumber())?0:Integer.parseInt(data.getDirectBusinessNumber().replace(",","")));
                    tWholeStationIndicators.setTotalPreSaleAmount(convertField(data.getTotalPreSaleAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getTotalPreSaleAmount().replace(",","")));
                    tWholeStationIndicators.setTotalPreSaleNumber(convertField(data.getTotalPreSaleNumber())?0:Integer.parseInt(data.getTotalPreSaleNumber().replace(",","")));
                    tWholeStationIndicators.setDirectPreSaleAmount(convertField(data.getDirectPreSaleAmount())? BigDecimal.valueOf(0) :new BigDecimal(data.getDirectPreSaleAmount().replace(",","")));
                    tWholeStationIndicators.setDirectPreSaleNumber(convertField(data.getDirectPreSaleNumber())?0:Integer.parseInt(data.getDirectPreSaleNumber().replace(",","")));
                    tWholeStationIndicators.setPreSaleRatio(convertField(data.getPreSaleRatio())?0:Double.parseDouble(data.getPreSaleRatio().replace(",","")));

                    tWholeStationIndicators.setCreateTime(new Date());
                    tWholeStationIndicators.setCreateBy(SecurityUtils.getUsername());
                    tWholeStationIndicators.setUserId(SecurityUtils.getUserId());
                    tWholeStationIndicators.setDeptId(SecurityUtils.getDeptId());


                    cachedDataList.add(tWholeStationIndicators);

                    // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
                    if (cachedDataList.size() >= BATCH_COUNT) {
                        //汇总需要清除的旧数据
                        List<String> deleteMainBodyIdList = cachedDataList.stream().map(TWholeStationIndicators::getMainBodyId).collect(Collectors.toList());
                        //清除旧数据
                        deleteOldData(fileId,wholeStoreId,cachedDataList.get(0).getStatDate(),deleteMainBodyIdList);
                        //存储新数据
                        saveBatch(cachedDataList);
                        // 存储完成清理 list
                        cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
                    }
                }

                /**
                 * 所有数据解析完成调用
                 *
                 * @param context
                 */
                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    if (!cachedDataList.isEmpty()){
                        //汇总需要清除的旧数据
                        List<String> deleteMainBodyIdList = cachedDataList.stream().map(TWholeStationIndicators::getMainBodyId).collect(Collectors.toList());
                        //清除旧数据
                        deleteOldData(fileId,wholeStoreId,cachedDataList.get(0).getStatDate(),deleteMainBodyIdList);
                        //存储新数据
                        saveBatch(cachedDataList);
                    }
                }
            }).excelType(CSV).charset(Charset.forName("GBK")).sheet().doRead();
        } catch (Exception e) {
            throw new RuntimeException("文件内容解析错误,文件上传失败!",e);
        }
    }

    /**
     * 判断字段
     * @param input
     * @return
     */
    public static boolean convertField(String input) {
        return input == null || input.isEmpty() || "-".equals(input);
    }

    private static final List<String> DATE_FORMATS = Arrays.asList(
            "yyyy-MM-dd",
            "yyyy/MM/dd"
    );

    /**
     * 解析日期字符串
     *
     * @param dateString
     * @return
     * @throws ParseException
     */
    public static Date parseDate(String dateString) throws ParseException {
        for (String format : DATE_FORMATS) {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat(format);
                sdf.setLenient(false); // 确保严格解析
                return sdf.parse(dateString);
            } catch (ParseException e) {
                // 尝试下一个格式
            }
        }
        throw new ParseException("无法解析日期: " + dateString, 0);
    }
}
